home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_addr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  5.4 KB  |  314 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_addr.c    7.4 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_re.h"
  13.  
  14. /*
  15.  * Routines for address parsing and assignment and checking of address bounds
  16.  * in command mode.  The routine address is called from ex_cmds.c
  17.  * to parse each component of a command (terminated by , ; or the beginning
  18.  * of the command itself.  It is also called by the scanning routine
  19.  * in ex_voperate.c from within open/visual.
  20.  *
  21.  * Other routines here manipulate the externals addr1 and addr2.
  22.  * These are the first and last lines for the current command.
  23.  *
  24.  * The variable bigmove remembers whether a non-local glitch of . was
  25.  * involved in an address expression, so we can set the previous context
  26.  * mark '' when such a motion occurs.
  27.  */
  28.  
  29. static    bool bigmove;
  30.  
  31. /*
  32.  * Set up addr1 and addr2 for commands whose default address is dot.
  33.  */
  34. setdot()
  35. {
  36.  
  37.     setdot1();
  38.     if (bigmove)
  39.         markDOT();
  40. }
  41.  
  42. /*
  43.  * Call setdot1 to set up default addresses without ever
  44.  * setting the previous context mark.
  45.  */
  46. setdot1()
  47. {
  48.  
  49.     if (addr2 == 0)
  50.         addr1 = addr2 = dot;
  51.     if (addr1 > addr2) {
  52.         notempty();
  53.         error("Addr1 > addr2|First address exceeds second");
  54.     }
  55. }
  56.  
  57. /*
  58.  * Ex allows you to say
  59.  *    delete 5
  60.  * to delete 5 lines, etc.
  61.  * Such nonsense is implemented by setcount.
  62.  */
  63. setcount()
  64. {
  65.     register int cnt;
  66.  
  67.     pastwh();
  68.     if (!isdigit(peekchar())) {
  69.         setdot();
  70.         return;
  71.     }
  72.     addr1 = addr2;
  73.     setdot();
  74.     cnt = getnum();
  75.     if (cnt <= 0)
  76.         error("Bad count|Nonzero count required");
  77.     addr2 += cnt - 1;
  78.     if (addr2 > dol)
  79.         addr2 = dol;
  80.     nonzero();
  81. }
  82.  
  83. /*
  84.  * Parse a number out of the command input stream.
  85.  */
  86. getnum()
  87. {
  88.     register int cnt;
  89.  
  90.     for (cnt = 0; isdigit(peekcd());)
  91.         cnt = cnt * 10 + ex_getchar() - '0';
  92.     return (cnt);
  93. }
  94.  
  95. /*
  96.  * Set the default addresses for commands which use the whole
  97.  * buffer as default, notably write.
  98.  */
  99. setall()
  100. {
  101.  
  102.     if (addr2 == 0) {
  103.         addr1 = one;
  104.         addr2 = dol;
  105.         if (dol == zero) {
  106.             dot = zero;
  107.             return;
  108.         }
  109.     }
  110.     /*
  111.      * Don't want to set previous context mark so use setdot1().
  112.      */
  113.     setdot1();
  114. }
  115.  
  116. /*
  117.  * No address allowed on, e.g. the file command.
  118.  */
  119. setnoaddr()
  120. {
  121.  
  122.     if (addr2 != 0)
  123.         error("No address allowed@on this command");
  124. }
  125.  
  126. /*
  127.  * Parse an address.
  128.  * Just about any sequence of address characters is legal.
  129.  *
  130.  * If you are tricky you can use this routine and the = command
  131.  * to do simple addition and subtraction of cardinals less
  132.  * than the number of lines in the file.
  133.  */
  134. line *
  135. address(inline)
  136.     char *inline;
  137. {
  138.     register line *addr;
  139.     register int offset, c;
  140.     short lastsign;
  141.  
  142.     bigmove = 0;
  143.     lastsign = 0;
  144.     offset = 0;
  145.     addr = 0;
  146.     for (;;) {
  147.         if (isdigit(peekcd())) {
  148.             if (addr == 0) {
  149.                 addr = zero;
  150.                 bigmove = 1;
  151.             }
  152.             loc1 = 0;
  153.             addr += offset;
  154.             offset = getnum();
  155.             if (lastsign >= 0)
  156.                 addr += offset;
  157.             else
  158.                 addr -= offset;
  159.             lastsign = 0;
  160.             offset = 0;
  161.         }
  162.         switch (c = getcd()) {
  163.  
  164.         case '?':
  165.         case '/':
  166.         case '$':
  167.         case '\'':
  168.         case '\\':
  169.             bigmove++;
  170.         case '.':
  171.             if (addr || offset)
  172.                 error("Badly formed address");
  173.         }
  174.         offset += lastsign;
  175.         lastsign = 0;
  176.         switch (c) {
  177.  
  178.         case ' ':
  179.         case '\t':
  180.             continue;
  181.  
  182.         case '+':
  183.             lastsign = 1;
  184.             if (addr == 0)
  185.                 addr = dot;
  186.             continue;
  187.  
  188.         case '^':
  189.         case '-':
  190.             lastsign = -1;
  191.             if (addr == 0)
  192.                 addr = dot;
  193.             continue;
  194.  
  195.         case '\\':
  196.         case '?':
  197.         case '/':
  198.             c = compile(c, 1);
  199.             notempty();
  200.             savere(scanre);
  201.             addr = dot;
  202.             if (inline && execute(0, dot)) {
  203.                 if (c == '/') {
  204.                     while (loc1 <= inline) {
  205.                         if (loc1 == loc2)
  206.                             loc2++;
  207.                         if (!execute(1))
  208.                             goto nope;
  209.                     }
  210.                     break;
  211.                 } else if (loc1 < inline) {
  212.                     char *last;
  213. doques:
  214.  
  215.                     do {
  216.                         last = loc1;
  217.                         if (loc1 == loc2)
  218.                             loc2++;
  219.                         if (!execute(1))
  220.                             break;
  221.                     } while (loc1 < inline);
  222.                     loc1 = last;
  223.                     break;
  224.                 }
  225.             }
  226. nope:
  227.             for (;;) {
  228.                 if (c == '/') {
  229.                     addr++;
  230.                     if (addr > dol) {
  231.                         if (value(WRAPSCAN) == 0)
  232. error("No match to BOTTOM|Address search hit BOTTOM without matching pattern");
  233.                         addr = zero;
  234.                     }
  235.                 } else {
  236.                     addr--;
  237.                     if (addr < zero) {
  238.                         if (value(WRAPSCAN) == 0)
  239. error("No match to TOP|Address search hit TOP without matching pattern");
  240.                         addr = dol;
  241.                     }
  242.                 }
  243.                 if (execute(0, addr)) {
  244.                     if (inline && c == '?') {
  245.                         inline = &linebuf[LBSIZE];
  246.                         goto doques;
  247.                     }
  248.                     break;
  249.                 }
  250.                 if (addr == dot)
  251.                     error("Fail|Pattern not found");
  252.             }
  253.             continue;
  254.  
  255.         case '$':
  256.             addr = dol;
  257.             continue;
  258.  
  259.         case '.':
  260.             addr = dot;
  261.             continue;
  262.  
  263.         case '\'':
  264.             c = markreg(ex_getchar());
  265.             if (c == 0)
  266.                 error("Marks are ' and a-z");
  267.             addr = getmark(c);
  268.             if (addr == 0)
  269.                 error("Undefined mark@referenced");
  270.             break;
  271.  
  272.         default:
  273.             ungetchar(c);
  274.             if (offset) {
  275.                 if (addr == 0)
  276.                     addr = dot;
  277.                 addr += offset;
  278.                 loc1 = 0;
  279.             }
  280.             if (addr == 0) {
  281.                 bigmove = 0;
  282.                 return (0);
  283.             }
  284.             if (addr != zero)
  285.                 notempty();
  286.             addr += lastsign;
  287.             if (addr < zero)
  288.                 error("Negative address@- first buffer line is 1");
  289.             if (addr > dol)
  290.                 error("Not that many lines@in buffer");
  291.             return (addr);
  292.         }
  293.     }
  294. }
  295.  
  296. /*
  297.  * Abbreviations to make code smaller
  298.  * Left over from squashing ex version 1.1 into
  299.  * 11/34's and 11/40's.
  300.  */
  301. setCNL()
  302. {
  303.  
  304.     setcount();
  305.     newline();
  306. }
  307.  
  308. setNAEOL()
  309. {
  310.  
  311.     setnoaddr();
  312.     eol();
  313. }
  314.